local guest = Client:addState("guest")

function guest:enteredState()
	print("client entered guest state")
	self.gui = {}
	--loveframes.SetState("game")
	--self:game_gui()
	--self:new_char_gui()
	local wu = love.graphics.newImage("assets/tilesets/woman_up.png")
	local wd = love.graphics.newImage("assets/tilesets/woman_down.png")
	local wl = love.graphics.newImage("assets/tilesets/woman_left.png")
	local wr = love.graphics.newImage("assets/tilesets/woman_right.png")


	self.anim = {}
	self.anim.woman_up = newAnimation(wu, 16, 32, 0.1, 0)
	self.anim.woman_down = newAnimation(wd, 16, 32, 0.1, 0)
	self.anim.woman_left = newAnimation(wl, 16, 32, 0.1, 0)
	self.anim.woman_right = newAnimation(wr, 16, 32, 0.1, 0)
	self.anim.woman_idle = love.graphics.newImage("assets/tilesets/woman_idle.png")
	self.anim.woman_idle_up = love.graphics.newImage("assets/tilesets/woman_idle_up.png")
	self.anim.woman_idle_right = love.graphics.newImage("assets/tilesets/woman_idle_right.png")
	self.anim.woman_idle_left = love.graphics.newImage("assets/tilesets/woman_idle_left.png")

	self.movement = "idle"



	self.nature_base = loader.load("assets/maps/nature_base.tmx")
	self.tech_base = loader.load("assets/maps/tech_base.tmx")
	self.scale = 4
	self.view_height = 768
	self.view_width = 1024
	self.jungle_start = 512
	self.jungle_end = 3104
	self.tile_size = 16
	self.authed = false
	self.turn_timer = 0.3
	self.turn = 0
	
	loveframes.SetState("client_guest")
	
	self.gui.frame = loveframes.Create("frame")
	self:login_frame()
	self:email_frame()

	self:loading_frame()

	self:user_input()
	self:p_input()

	self:choose_team_gui()
	
	self.stats = {}

	self.cmd_patterns = {
	"%[energy%]",
	"%[grit%]",
	"%[concentration%]",
	"%[might%]",
	"%[persistence%]",
	"%[coordination%]",
	"%[lithe%]",
	"%[understanding%]",
	"%[resolve%]",
	"%[kismet%]",
	"%[run%]",
	"%[jump%]",
	"%[light_melee%]",
	"%[heavy_melee%]",
	"%[light_ranged%]",
	"%[heavy_ranged%]",
	"%[akimbo%]",
	"%[stealth%]",
	"%[detect_stealth%]",
	"%[locksmithing%]",
	"%[tracking%]",
	"%[trapping%]",
	"%[melee_d%]",
	"%[ranged_d%]",
	"%[kidnapping%]",
	"%[interrogation%]",
	"%[escape%]",
	"%[tolerance%]",
	"%[elementalism%]",
	"%[chaos%]",
	"%[blessing%]",
	"%[summoning%]",
	"%[mentalism%]",
	"%[demolitions%]",
	"%[medicine%]",
	"%[mechanics%]",
	"%[cyber%]",
	"%[psychology%]",
	"%[make_new_char%]",
	"%[training_points%]",
	"%[character_points%]",
	"%[name%]",
	"%[gender%]",
	"%[enter_game%]",
	"%[chat%]",
	"%[current_map%]",
	"%[extra_tiles%]",
	"%[setX%]",
	"%[setY%]",
	"%[guest_pos%]",
	"%[setIP%]"

	}
	

end

function guest:update(dt)
	local lfc = love.thread.getChannel("lf_state")
	local client_response = love.thread.getChannel("client_response")
	local guest_authed = love.thread.getChannel("guest_authed")
	local server_cmd = love.thread.getChannel("server_commands")

	if lfc:peek() == "client_guest_pass" then
		lfc:pop()
		loveframes.SetState("client_guest_pass")
	end

	if client_response:peek() == "quit" then
		client_response:pop()
		love.event.quit()
	end

	if guest_authed:peek() == "true" then
		self.authed = true
		guest_authed:pop()
		self:remove_login_gui()
		self:game_gui()
		self:char_info_gui()
		self:chat_gui()
		self:chat_input_gui()
	end

	if server_cmd:peek() then
		print("server command received, parsing " .. server_cmd:peek())
		local cmds = self:parse(server_cmd:pop())
		if cmds then
			for i = 1, #cmds do
				if cmds[i].cmd == "[energy]" then
					self:update_stat("energy", cmds[i].data) 					
				elseif cmds[i].cmd == "[grit]" then
					self:update_stat("grit", cmds[i].data) 
				elseif cmds[i].cmd == "[concentration]" then
					self:update_stat("concentration", cmds[i].data) 
				elseif cmds[i].cmd == "[might]" then
					self:update_stat("might", cmds[i].data) 
				elseif cmds[i].cmd == "[persistence]" then
					self:update_stat("persistence", cmds[i].data) 
				elseif cmds[i].cmd == "[coordination]" then
					self:update_stat("coordination", cmds[i].data) 
				elseif cmds[i].cmd == "[lithe]" then
					self:update_stat("lithe", cmds[i].data) 
				elseif cmds[i].cmd == "[understanding]" then
					self:update_stat("understanding", cmds[i].data) 
				elseif cmds[i].cmd == "[resolve]" then
					self:update_stat("resolve", cmds[i].data) 
				elseif cmds[i].cmd == "[kismet]" then
					self:update_stat("kismet", cmds[i].data)
				elseif cmds[i].cmd == "[run]" then
					self:update_stat("run", cmds[i].data) 
				elseif cmds[i].cmd == "[jump]" then
					self:update_stat("jump", cmds[i].data) 
				elseif cmds[i].cmd == "[light_melee]" then
					self:update_stat("light_melee", cmds[i].data) 
				elseif cmds[i].cmd == "[heavy_melee]" then
					self:update_stat("heavy_melee", cmds[i].data) 
				elseif cmds[i].cmd == "[light_ranged]" then
					self:update_stat("light_ranged", cmds[i].data) 
				elseif cmds[i].cmd == "[heavy_ranged]" then
					self:update_stat("heavy_ranged", cmds[i].data) 
				elseif cmds[i].cmd == "[akimbo]" then
					self:update_stat("akimbo", cmds[i].data) 
				elseif cmds[i].cmd == "[stealth]" then
					self:update_stat("stealth", cmds[i].data) 
				elseif cmds[i].cmd == "[detect_stealth]" then
					self:update_stat("detect_stealth", cmds[i].data) 
				elseif cmds[i].cmd == "[locksmithing]" then
					self:update_stat("locksmithing", cmds[i].data) 
				elseif cmds[i].cmd == "[tracking]" then
					self:update_stat("tracking", cmds[i].data) 
				elseif cmds[i].cmd == "[trapping]" then
					self:update_stat("trapping", cmds[i].data) 
				elseif cmds[i].cmd == "[melee_d]" then
					self:update_stat("melee_d", cmds[i].data) 
				elseif cmds[i].cmd == "[ranged_d]" then
					self:update_stat("ranged_d", cmds[i].data) 
				elseif cmds[i].cmd == "[kidnapping]" then
					self:update_stat("kidnapping", cmds[i].data) 
				elseif cmds[i].cmd == "[interrogation]" then
					self:update_stat("interrogation", cmds[i].data) 
				elseif cmds[i].cmd == "[escape]" then
					self:update_stat("escape", cmds[i].data) 
				elseif cmds[i].cmd == "[tolerance]" then
					self:update_stat("tolerance", cmds[i].data) 
				elseif cmds[i].cmd == "[elementalism]" then
					self:update_stat("elementalism", cmds[i].data) 
				elseif cmds[i].cmd == "[chaos]" then
					self:update_stat("chaos", cmds[i].data) 
				elseif cmds[i].cmd == "[blessing]" then
					self:update_stat("blessing", cmds[i].data) 
				elseif cmds[i].cmd == "[summoning]" then
					self:update_stat("summoning", cmds[i].data) 
				elseif cmds[i].cmd == "[mentalism]" then
					self:update_stat("mentalism", cmds[i].data) 
				elseif cmds[i].cmd == "[demolitions]" then
					self:update_stat("demolitions", cmds[i].data) 
				elseif cmds[i].cmd == "[medicine]" then
					self:update_stat("medicine", cmds[i].data) 
				elseif cmds[i].cmd == "[mechanics]" then
					self:update_stat("mechanics", cmds[i].data) 
				elseif cmds[i].cmd == "[cyber]" then
					self:update_stat("cyber", cmds[i].data) 
				elseif cmds[i].cmd == "[psychology]" then
					self:update_stat("psychology", cmds[i].data) 
				elseif cmds[i].cmd == "[make_new_char]" then
					self:new_char_gui()
				elseif cmds[i].cmd == "[training_points]" then
					self:update_stat("training_points", cmds[i].data)
					self:update_stat("training_points_max", cmds[i].data)
				elseif cmds[i].cmd == "[character_points]" then
					self:update_stat("character_points", cmds[i].data)
					self:update_stat("character_points_max", cmds[i].data)
				elseif cmds[i].cmd == "[name]" then
					self:update_stat("name", cmds[i].data)
				elseif cmds[i].cmd == "[gender]" then
					self:update_stat("gender", cmds[i].data)
				elseif cmds[i].cmd == "[enter_game]" then
					self:join_game()
				elseif cmds[i].cmd == "[chat]" then
					self:add_to_chat(cmds[i].data)
				elseif cmds[i].cmd == "[current_map]" then
					self:load_map(cmds[i].data)
				elseif cmds[i].cmd == "[extra_tiles]" then
					self:add_extra_tiles(cmds[i].data)
				elseif cmds[i].cmd == "[setX]" then
					self:setX(cmds[i].data)
				elseif cmds[i].cmd == "[setY]" then
					self:setY(cmds[i].data)
				elseif cmds[i].cmd == "[guest_pos]" then
					self:set_guest_locations(cmds[i].data)
				elseif cmds[i].cmd == "[setIP]" then
					print("setting IP to " .. cmds[i].data)
					self.ip = cmds[i].data
				end
			end
		end
	end

	if self.authed then

		if self.turn > self.turn_timer then
			self.turn = 0

			if self.movement ~= "idle" then
				local s = "move_" .. self.movement
				local cc = love.thread.getChannel("client_command")
				cc:push(s)
			end

		end

	end
	

	self.anim.woman_up:update(dt)
	self.anim.woman_down:update(dt)
	self.anim.woman_right:update(dt)
	self.anim.woman_left:update(dt)
	self.turn = self.turn + dt
	
end

function guest:keypressed(key, isRepeat)
	if key == "return" then
		if self.gui.chat_input_text then		
			local focus = self.gui.chat_input_text:GetFocus()
			if not focus then
				self.gui.chat_input_text:SetFocus(true)
			end
		end
	end

	if key == "up" then	
		self:move_control(key)
	elseif key == "down" then
		self:move_control(key)
	elseif key == "left" then
		self:move_control(key)
	elseif key == "right" then
		self:move_control(key)
	end



end

function guest:move_control(dir)
	self.movement = dir
	local s = "move_" .. dir
	local cc = love.thread.getChannel("client_command")
	cc:push(s)
end

function guest:keyreleased(key)
	if key == "up" or key == "down" or key == "left" or key == "right" then
		self.prev_movement = key
		self.movement = "idle"
	end
end



function guest:load_map(map_string)
	self.jungle = loader.load_from_string("jungle", map_string)
	self.jungle_loaded = true
	print("jungle loaded")
end
---
function guest:add_extra_tiles(extra_tiles)
	local et1, num = extra_tiles:gsub("(%a)", "%[\"%1\"%]")
	print("extra tiles .. " .. et1)



	local s = "return " .. et1

	local chunk = loadstring(s)

	local et = chunk()	
	
	for i = 1, #et do
		local layer
		if et[i].v <= 12 then
			layer = "ground"
		else
			layer = "ground_decor"
		end
		self.jungle.layers[layer]:set(et[i].x, et[i].y, self.jungle.tiles[et[i].v])
	end
	
	
end

function guest:draw()
	if self.jungle_loaded and self.x and self.y then
		local ftx, fty = math.floor(self.x-(self.view_width/2)/self.scale), math.floor(self.y-(self.view_height/2)/self.scale)
		love.graphics.push()
		love.graphics.scale(self.scale)
		love.graphics.translate(-ftx, -fty)
		self.nature_base:setDrawRange(ftx, fty, ftx+(self.view_width/self.scale), fty+(self.view_height/self.scale))
		self.nature_base:draw()
		self.tech_base:setDrawRange(ftx, fty-(self.jungle_end*self.scale), 
			ftx+(self.view_width/self.scale), fty+(self.view_height/self.scale))	
		self.jungle:setDrawRange(ftx, fty-(self.jungle_start*self.scale), 
			ftx+(self.view_width/self.scale), fty+(self.view_height/self.scale))
		self.tech_base:draw()
		self.jungle:draw()

		local offX = self.x
		local offY = self.y+self.tile_size/2

		if self.movement == "idle" then
			if not self.prev_movement or self.prev_movement == "down" then
				love.graphics.draw(self.anim.woman_idle, offX, offY, 0, nil, nil, 8, 16 )
			elseif self.prev_movement == "up" then
				love.graphics.draw(self.anim.woman_idle_up, offX, offY, 0, nil, nil, 8, 16 )
			elseif self.prev_movement == "right" then
				love.graphics.draw(self.anim.woman_idle_right, offX, offY, 0, nil, nil, 8, 16)
			elseif self.prev_movement == "left" then
				love.graphics.draw(self.anim.woman_idle_left, offX, offY, 0, nil, nil, 8, 16)
			end			
		elseif self.movement == "up" then
			self.anim.woman_up:draw(offX, offY, 0, nil, nil, 8, 16)
		elseif self.movement == "down" then
			self.anim.woman_down:draw(offX, offY, 0, nil, nil, 8, 16)
		elseif self.movement == "right" then
			self.anim.woman_right:draw(offX, offY, 0, nil, nil, 8, 16)
		elseif self.movement == "left" then
			self.anim.woman_left:draw(offX, offY, 0, nil, nil, 8, 16)
		end

		if self.all_guests then
			for i = 1, #self.all_guests do
				if self.all_guests[i].ip ~= self.ip then
					love.graphics.draw(self.anim.woman_idle, self.all_guests[i].x, self.all_guests[i].y, 0, nil, nil, 8, 16)
				end
			end
		end

		love.graphics.pop()

	end



end

function guest:set_guest_locations(gstring)
	if gstring then
		print("gstring: " .. gstring)
		local chunk = loadstring("return " .. gstring)
		local gs = chunk()

		for i = #gs, 1, -1 do
			if gs[i].x == self.x and gs[i].y == self.y then			
				table.remove(gs, i)
			end
		end
		self.all_guests = gs
	end

end

function guest:join_game()
	self.gui.char_info_frame:SetVisible(true)
	self.gui.frame:SetVisible(false)
	self.gui.chat_frame:SetVisible(true)
	self.gui.chat_input_panel:SetVisible(true)
	
end



function guest:parse(text)
	print("parsing " .. text)
	local results = {}
	for i = 1, #self.cmd_patterns do
		print("testing cmd pattern " .. self.cmd_patterns[i])
		local s, e = text:find(self.cmd_patterns[i])
		if s and e then
			print("command found starting at char " .. s .. " ending at char " .. e)
			local iter = #results+1
			results[iter] = {}
			results[iter].cmd = text:sub(s, e)
			results[iter].data = text:sub(e+1)
		end
	end
	if #results > 0 then return results else return nil end
end



function guest:login_frame()
	self.gui.frame:SetSize(500, 90)
	self.gui.frame:Center()
	self.gui.frame:SetDraggable(false)
	self.gui.frame:ShowCloseButton(false)
	self.gui.frame:SetResizable(false)
	self.gui.frame:SetDockable(false)
end
function guest:email_frame()
	self.gui.frame:SetName("Email Address")	
	self.gui.frame:SetState("client_guest")	
end

function guest:pass_frame()
	self.gui.frame:SetState("client_guest_pass")
	self.gui.frame:SetName("Password")	
end

function guest:loading_frame()
	self.gui.loading_frame = loveframes.Create("frame")
	self.gui.loading_frame:SetName("Loading...")
	self.gui.loading_frame:SetSize(100, 20)
	self.gui.loading_frame:Center()
	self.gui.loading_frame:SetState("loading")
	self.gui.loading_frame:SetAlwaysUpdate(false)
end

function guest:choose_team_gui()
	self.gui.choose_team_frame = loveframes.Create("frame")
	local f = self.gui.choose_team_frame
	f:SetName("Choose Team")
	f:Center()
	f:SetState("game")
	self:make_static_frame(f, true)

	self.gui.choose_team_mc = loveframes.Create("multichoice", f)
	local mc = self.gui.choose_team_mc
	mc:AddChoice("Nature")
	mc:AddChoice("Tech")
	mc:Center()
	mc.OnChoiceSelected = function(object, choice)
		local cc = love.thread.getChannel("client_command")
		cc:push("team_selection")
		cc:push(choice)
		object:GetParent():SetVisible(false)
	end


end

function guest:user_input()
	self.gui.user_name_input = loveframes.Create("textinput", frame)
	self.gui.user_name_input:SetWidth(490)
	self.gui.user_name_input:Center()	
	self.gui.user_name_input:SetState("client_guest")
	self.gui.user_name_input:SetFocus(true)
	self.gui.user_name_input.OnEnter = function(object, text)
		if text then
			local enc_text = sha256(text)
			self.preauth_email = text			
			local cc = love.thread.getChannel("client_command")
			cc:push("email_stream")
			cc:push(enc_text)			
			loveframes.SetState("loading")
			self:pass_frame()
			self.gui.pass_input:SetFocus(true)
			

		end
	end
end

function guest:p_input()
	self.gui.pass_input = loveframes.Create("textinput", frame)
	self.gui.pass_input:SetWidth(490)
	self.gui.pass_input:Center()
	self.gui.pass_input:SetState("client_guest_pass")
	self.gui.pass_input.OnEnter = function(object, text)
		if text then
			local enc_text = sha256(text)
			local cc = love.thread.getChannel("client_command")
			cc:push("pass_stream")
			cc:push(enc_text)			
			loveframes.SetState("loading")
		end

	end
end

function guest:remove_login_gui()
	self.gui.frame:Remove()
	self.gui.user_name_input:Remove()
	self.gui.pass_input:Remove()
end

function guest:remove_all_gui()
	local obj = loveframes.util.GetAllObjects()
	for i = 1, #obj do
		obj:Remove()
	end
end


function guest:game_gui()
	loveframes.SetState("game")
	self.gui.frame = loveframes.Create("frame")
	self:login_frame()
	self.gui.frame:SetSize(565, 525)	
	self.gui.frame:Center()
	--self.gui.frame:SetY(50)
	self.gui.frame:SetName("Game")
	self.gui.frame:SetState("game")


end

function guest:new_char_gui()
	loveframes.SetState("game")
	self.gui.frame:SetName("New Character")
	self.gui.new_char_submit = loveframes.Create("button", self.gui.frame)
	local b = self.gui.new_char_submit
	b:SetText("Submit")
	b:CenterX()
	b:SetY(530)
	b.OnClick = function(object, x, y)
		local trained_skills = self:get_property_in_list(self.gui.train_buttons, "mastery", "trained")
		local spec_skills = self:get_property_in_list(self.gui.train_buttons, "mastery", "specialized")
		self:submit_new_char(self.gui.new_char_name_input:GetText(), 
			self.gui.select_gender:GetChoice(), 
			self.gui.might_slider:GetValue(),
			self.gui.persistence_slider:GetValue(),
			self.gui.coordination_slider:GetValue(),
			self.gui.lithe_slider:GetValue(),
			self.gui.understanding_slider:GetValue(),
			self.gui.resolve_slider:GetValue(),
			self.gui.kismet_slider:GetValue(),
			trained_skills,
			spec_skills)

	end

	self.gui.new_char_name_frame = loveframes.Create("frame", self.gui.frame)
	local f = self.gui.new_char_name_frame
	f:SetName("Name")
	f:SetWidth("100")
	f:SetHeight("65")
	f:SetPos(5, 30)
	self:make_static_frame(f)	
	self.gui.new_char_name_input = loveframes.Create("textinput", self.gui.new_char_name_frame)  
	local ci = self.gui.new_char_name_input
	ci:SetWidth(90)
	ci:Center()
	ci:SetY(30)
	self.gui.new_char_gender_frame = loveframes.Create("frame", self.gui.frame)
	f = self.gui.new_char_gender_frame
	f:SetName("Gender")
	f:SetWidth("135")
	f:SetHeight("65")
	f:SetPos(110, 30)
	self:make_static_frame(f)
	self.gui.select_gender = loveframes.Create("multichoice", self.gui.new_char_gender_frame)
	local sg = self.gui.select_gender
	sg:SetWidth("125")
	sg:Center()
	sg:SetY(30)
	sg:AddChoice("man")
	sg:AddChoice("woman")	
	sg:AddChoice("both")
	sg:AddChoice("unknown")

	self.gui.primary_stat_frame = loveframes.Create("frame", self.gui.frame)
	f = self.gui.primary_stat_frame
	f:SetName("Starting Stats")
	f:SetWidth("240")
	f:SetHeight("415")
	f:SetPos(5, 100)
	self:make_static_frame(f)

	self.gui.character_points = loveframes.Create("text", self.gui.primary_stat_frame)
	local cp = self.gui.character_points
	cp:SetText(self.character_points)
	cp:SetPos(210, 5)

	self.gui.might_slider_frame = loveframes.Create("frame", self.gui.primary_stat_frame)
	f = self.gui.might_slider_frame
	f:SetName("Might")
	f:SetWidth("230")
	f:SetHeight("50")	
	f:SetPos(5, 30)
	self:make_static_frame(f)

	self.gui.might_slider = loveframes.Create("slider", self.gui.might_slider_frame)
	local s = self.gui.might_slider
	s:SetWidth(185)
	s:SetX(5)
	s:SetY(25)
	s:SetMinMax(10, 100)
	s:SetDecimals(0)	
	s.OnValueChanged = function(object)
		print("slider set to " .. object:GetValue())
		self.gui.might_slider_text:SetText(object:GetValue())
		self:update_stat_slider_gui(object)
		object:SetProperty("prev_position", object:GetValue())
	end

	self.gui.might_slider_text = loveframes.Create("text", self.gui.might_slider_frame)
	local t = self.gui.might_slider_text
	t:SetWidth(50)
	t:SetX(200)
	t:SetY(27)
	t:SetText(self.gui.might_slider:GetValue())

	self.gui.persistence_slider_frame = loveframes.Create("frame", self.gui.primary_stat_frame)
	f = self.gui.persistence_slider_frame
	f:SetName("Persistence")
	f:SetSize(230, 50)
	f:SetPos(5, 85)
	self:make_static_frame(f)

	self.gui.persistence_slider = loveframes.Create("slider", self.gui.persistence_slider_frame)
	s = self.gui.persistence_slider
	s:SetWidth(185)
	s:SetX(5)
	s:SetY(25)
	s:SetMinMax(10, 100)
	s:SetDecimals(0)
	s.OnValueChanged = function(object)
		print("slider set to " .. object:GetValue())
		self.gui.persistence_slider_text:SetText(object:GetValue())
		self:update_stat_slider_gui(object)
		object:SetProperty("prev_position", object:GetValue())
	end

	self.gui.persistence_slider_text = loveframes.Create("text", self.gui.persistence_slider_frame)
	local t = self.gui.persistence_slider_text
	t:SetWidth(50)
	t:SetX(200)
	t:SetY(27)
	t:SetText(self.gui.persistence_slider:GetValue())

	self.gui.coordination_slider_frame = loveframes.Create("frame", self.gui.primary_stat_frame)
	f = self.gui.coordination_slider_frame
	f:SetName("Coordination")
	f:SetSize(230, 50)
	f:SetPos(5, 140)
	self:make_static_frame(f)

	self.gui.coordination_slider = loveframes.Create("slider", self.gui.coordination_slider_frame)
	s = self.gui.coordination_slider
	s:SetWidth(185)
	s:SetX(5)
	s:SetY(25)
	s:SetMinMax(10, 100)
	s:SetDecimals(0)
	s.OnValueChanged = function(object)
		print("slider set to " .. object:GetValue())
		self.gui.coordination_slider_text:SetText(object:GetValue())
		self:update_stat_slider_gui(object)
		object:SetProperty("prev_position", object:GetValue())
	end

	self.gui.coordination_slider_text = loveframes.Create("text", self.gui.coordination_slider_frame)
	local t = self.gui.coordination_slider_text
	t:SetWidth(50)
	t:SetX(200)
	t:SetY(27)
	t:SetText(self.gui.coordination_slider:GetValue())

	self.gui.lithe_slider_frame = loveframes.Create("frame", self.gui.primary_stat_frame)
	f = self.gui.lithe_slider_frame
	f:SetName("Lithe")
	f:SetSize(230, 50)
	f:SetPos(5, 195)
	self:make_static_frame(f)

	self.gui.lithe_slider = loveframes.Create("slider", self.gui.lithe_slider_frame)
	s = self.gui.lithe_slider
	s:SetWidth(185)
	s:SetX(5)
	s:SetY(25)
	s:SetMinMax(10, 100)
	s:SetDecimals(0)
	s.OnValueChanged = function(object)
		print("slider set to " .. object:GetValue())
		self.gui.lithe_slider_text:SetText(object:GetValue())
		self:update_stat_slider_gui(object)
		object:SetProperty("prev_position", object:GetValue())
	end

	self.gui.lithe_slider_text = loveframes.Create("text", self.gui.lithe_slider_frame)
	local t = self.gui.lithe_slider_text
	t:SetWidth(50)
	t:SetX(200)
	t:SetY(27)
	t:SetText(self.gui.lithe_slider:GetValue())

	self.gui.understanding_slider_frame = loveframes.Create("frame", self.gui.primary_stat_frame)
	f = self.gui.understanding_slider_frame
	f:SetName("Understanding")
	f:SetSize(230, 50)
	f:SetPos(5, 250)
	self:make_static_frame(f)

	self.gui.understanding_slider = loveframes.Create("slider", self.gui.understanding_slider_frame)
	s = self.gui.understanding_slider
	s:SetWidth(185)
	s:SetX(5)
	s:SetY(25)
	s:SetMinMax(10, 100)
	s:SetDecimals(0)
	s.OnValueChanged = function(object)
		print("slider set to " .. object:GetValue())
		self.gui.understanding_slider_text:SetText(object:GetValue())
		self:update_stat_slider_gui(object)
		object:SetProperty("prev_position", object:GetValue())
	end

	self.gui.understanding_slider_text = loveframes.Create("text", self.gui.understanding_slider_frame)
	local t = self.gui.understanding_slider_text
	t:SetWidth(50)
	t:SetX(200)
	t:SetY(27)
	t:SetText(self.gui.understanding_slider:GetValue())

	self.gui.resolve_slider_frame = loveframes.Create("frame", self.gui.primary_stat_frame)
	f = self.gui.resolve_slider_frame
	f:SetName("Resolve")
	f:SetSize(230, 50)
	f:SetPos(5, 305)
	self:make_static_frame(f)

	self.gui.resolve_slider = loveframes.Create("slider", self.gui.resolve_slider_frame)
	s = self.gui.resolve_slider
	s:SetWidth(185)
	s:SetX(5)
	s:SetY(25)
	s:SetMinMax(10, 100)
	s:SetDecimals(0)
	s.OnValueChanged = function(object)
		print("slider set to " .. object:GetValue())
		self.gui.resolve_slider_text:SetText(object:GetValue())
		self:update_stat_slider_gui(object)
		object:SetProperty("prev_position", object:GetValue())
	end

	self.gui.resolve_slider_text = loveframes.Create("text", self.gui.resolve_slider_frame)
	local t = self.gui.resolve_slider_text
	t:SetWidth(50)
	t:SetX(200)
	t:SetY(27)
	t:SetText(self.gui.resolve_slider:GetValue())

	self.gui.kismet_slider_frame = loveframes.Create("frame", self.gui.primary_stat_frame)
	f = self.gui.kismet_slider_frame
	f:SetName("Kismet")
	f:SetSize(230, 50)
	f:SetPos(5, 360)
	self:make_static_frame(f)

	self.gui.kismet_slider = loveframes.Create("slider", self.gui.kismet_slider_frame)
	s = self.gui.kismet_slider
	s:SetWidth(185)
	s:SetX(5)
	s:SetY(25)
	s:SetMinMax(10, 100)
	s:SetDecimals(0)
	s.OnValueChanged = function(object)
		print("slider set to " .. object:GetValue())
		self.gui.kismet_slider_text:SetText(object:GetValue())
		self:update_stat_slider_gui(object)
		object:SetProperty("prev_position", object:GetValue())
	end

	self.gui.kismet_slider_text = loveframes.Create("text", self.gui.kismet_slider_frame)
	local t = self.gui.kismet_slider_text
	t:SetWidth(50)
	t:SetX(200)
	t:SetY(27)
	t:SetText(self.gui.kismet_slider:GetValue())

	self:update_stat_slider_gui()

	self:new_train_gui()

end

function guest:new_train_gui()
	self.gui.new_train_frame = loveframes.Create("frame", self.gui.frame)
	local f = self.gui.new_train_frame
	f:SetName("Skills")
	f:SetPos(250, 30)
	f:SetSize(310, 485)
	self:make_static_frame(f)
	self.gui.training_points = loveframes.Create("text", self.gui.new_train_frame)
	local tp = self.gui.training_points
	tp:SetText(self.training_points)
	tp:SetPos(275, 5)

	local list_height = 100
	local padding = 5
	local originY = 50
	self.gui.unspec_list_label = loveframes.Create("text", self.gui.new_train_frame)
	self.gui.unspec_list = loveframes.Create("list", self.gui.new_train_frame)
	local ul = self.gui.unspec_list
	local ult = self.gui.unspec_list_label
	self.gui.train_list_label = loveframes.Create("text", self.gui.new_train_frame)
	self.gui.train_list = loveframes.Create("list", self.gui.new_train_frame)
	local tl = self.gui.train_list
	local tlt = self.gui.train_list_label
	self.gui.spec_list_label = loveframes.Create("text", self.gui.new_train_frame)
	self.gui.spec_list = loveframes.Create("list", self.gui.new_train_frame)
	local sl = self.gui.spec_list
	local slt = self.gui.spec_list_label
	sl:SetPos(5, originY)	
	sl:SetHeight(list_height)
	sl:SetAutoScroll(true)
	slt:SetPos(5, originY-20)
	slt:SetText("Specialized")
	tl:SetPos(5, originY + list_height+ padding+20)
	tl:SetHeight(list_height)
	tl:SetAutoScroll(true)
	tlt:SetPos(5, (originY + list_height+ padding))
	tlt:SetText("Trained")
	ul:SetPos(5, originY + (2*list_height) + (2*padding)+40)
	ul:SetHeight(list_height+70)
	ul:SetAutoScroll(true)
	ult:SetPos(5, originY + (2*list_height) + (2*padding)+20)
	ult:SetText("Untrained")
	self.gui.train_buttons = {}
	local tb = self.gui.train_buttons
	for i = 1, #self.train_list do
		self:training_list_button(tb, self.train_list[i], ul, tl, sl)				
	end
end

function guest:get_property_in_list(list, property, desiredValue)
	local text = {}
	print(#list)
	for i = 1, #list do
		local p = list[i]:GetProperty(property)
		if p == desiredValue then
			text[#text+1] = list[i]:GetText()
		end
		print(list[i]:GetText())
	end
	return text
end

function guest:submit_new_char(name, gender, might, persistence, coordination, lithe, understanding, resolve, kismet, trained, spec)
	
	print("submit new char ", name, gender, might, persistence, coordination, lithe, understanding, resolve, kismet)
	local char_points_test = false
	local train_points_test = false

	local spec_cost = 0
	local train_cost = 0

	for i = 1, #trained do
		print(trained[i])
		train_cost = train_cost + self.skill_cost_list[trained[i]]["train"]
	end
	for i = 1, #spec do
		print(spec[i])
		spec_cost = spec_cost + self.skill_cost_list[spec[i]]["spec"]
	end
	print("tp cost " .. spec_cost+train_cost, "tp max " .. self.training_points_max)

	if spec_cost + train_cost <= tonumber(self.training_points_max) then
		train_points_test = true
	end

	print("cp total: " .. might+persistence+coordination+lithe+understanding+resolve+kismet)
	if might + persistence + coordination + lithe + understanding + resolve + kismet == tonumber(self.character_points_max) then
		char_points_test = true
	end
	if train_points_test then
		print("train test true")
	end
	if char_points_test then
		print("cp test true")
	end

	if train_points_test and char_points_test then
		print("tests passed")
		local cmd = love.thread.getChannel("client_command")
		cmd:push("new_stat_stream")
		cmd:push("[might]"..might)
		cmd:push("new_stat_stream")
		cmd:push("[persistence]"..persistence)
		cmd:push("new_stat_stream")
		cmd:push("[coordination]"..coordination)
		cmd:push("new_stat_stream")
		cmd:push("[lithe]"..lithe)
		cmd:push("new_stat_stream")
		cmd:push("[understanding]"..understanding)
		cmd:push("new_stat_stream")
		cmd:push("[resolve]"..resolve)
		cmd:push("new_stat_stream")
		cmd:push("[kismet]"..kismet)
		cmd:push("new_stat_stream")
		cmd:push("[name]"..name)
		cmd:push("new_stat_stream")
		cmd:push("[gender]"..gender)
		cmd:push("stat_stream_finished")
		for i = 1, #trained do
			cmd:push("new_skill_train_stream")
			cmd:push(trained[i])
		end
		for i = 1, #spec do
			cmd:push("new_skill_spec_stream")
			cmd:push(spec[i])
		end
		cmd:push("skill_stream_finished")
	else
		return false
	end


end

function guest:training_list_button(tb, text, ul, tl, sl)
	local tbi = #tb+1
	tb[tbi] = loveframes.Create("button")
	local button = tb[tbi]
	button:SetText(text)
	button:SetProperty("mastery", "untrained")
	button.OnClick = function(object, x, y)
		local mast = object:GetProperty("mastery")		
		if mast == "untrained" then 
			if self.training_points - self.skill_cost_list[object:GetText()]["train"] >= 0 then
				object:SetProperty("mastery", "trained")				
				self:update_stat("training_points", self.training_points - self.skill_cost_list[object:GetText()]["train"]) 
			end
		elseif mast == "trained" then
			if self.training_points - self.skill_cost_list[object:GetText()]["spec"] >= 0 then					
				object:SetProperty("mastery", "specialized")
				self:update_stat("training_points", self.training_points - self.skill_cost_list[object:GetText()]["spec"]) 
			else
				self:update_stat("training_points", self.training_points + self.skill_cost_list[object:GetText()]["train"])
				object:SetProperty("mastery", "untrained")
			end
		elseif mast == "specialized" then				
			object:SetProperty("mastery", "untrained")
			self:update_stat("training_points", self.training_points + self.skill_cost_list[object:GetText()]["spec"] + 
				self.skill_cost_list[object:GetText()]["train"])
		end
		self:set_train_button_list(object, ul, tl, sl)
	end
	self:set_train_button_list(button, ul, tl, sl)

end

function guest:set_train_button_list(button, unspec_list, train_list, spec_list)
	local mast = button:GetProperty("mastery")
	print(mast)
	--unspec_list:RemoveItem(button)
	--train_list:RemoveItem(button)
	--spec_list:RemoveItem(button)
	if mast == "untrained" then
		
		unspec_list:AddItem(button, true)
		
		
	elseif mast == "trained" then
		
		train_list:AddItem(button, true)
		
		
	elseif mast == "specialized" then
		
		spec_list:AddItem(button, true)
	
		
	end

end

function guest:update_stat_slider_gui(object)
	local total = self.gui.might_slider:GetValue() + self.gui.persistence_slider:GetValue() + self.gui.coordination_slider:GetValue() +
		self.gui.lithe_slider:GetValue() + self.gui.understanding_slider:GetValue() + self.gui.resolve_slider:GetValue() + 
		self.gui.kismet_slider:GetValue()
	print("total character points spent " .. total)
	if total > tonumber(self.character_points_max) then
		local pp = object:GetProperty("prev_position")
		if pp then
			object:SetValue(object:GetProperty("prev_position"))
		else
			object:SetValue(10)
		end
	else
		self:update_stat("character_points", self.character_points_max - total) 
	end	

end



function guest:make_static_frame(f, nd, rz)
	if not nd then f:SetDraggable(false) end
	f:ShowCloseButton(false)
	if not rz then f:SetResizable(false) else f:SetResizable(true) end
	f:SetDockable(false)
end

function guest:char_info_gui()
	self.gui.char_info_frame = loveframes.Create("frame")
	local frame = self.gui.char_info_frame
	frame:SetName("Character Info")
	frame:SetSize(160, 500)
	frame:SetPos(20, 20)
	frame:SetState("game")
	frame:SetVisible(false)
	self:make_static_frame(frame, true)


	self.gui.char_info_panel = loveframes.Create("list", self.gui.char_info_frame)
	local list = self.gui.char_info_panel
	list:SetPos(5, 30)
	list:SetSize(150, 465)
	list:SetPadding(5)
	list:SetSpacing(5)
	list:SetState("game")
	if self.stats then	
		self:gui_list_stats(list)		
	end
end

function guest:chat_gui()
	local w,h = love.window.getDimensions()
	self.gui.chat_frame = loveframes.Create("frame")
	local f = self.gui.chat_frame
	f:SetName("Chat")
	f:SetSize(300, 100)
	f:SetPos(w-320, h-120)
	f:SetVisible(false)
	f:SetState("game")
	self:make_static_frame(f, true, true)
	self.gui.chat_list = loveframes.Create("list", f)
	local l = self.gui.chat_list
	l:SetPos(5, 30)
	l:SetSize(290, 65)
end

function guest:chat_input_gui()
	local w, h = love.window.getDimensions()
	self.gui.chat_input_panel = loveframes.Create("frame")
	local p = self.gui.chat_input_panel
	p:SetSize(400, 30)
	p:SetPos(20, h-50)	
	p:SetState("game")
	p:SetVisible(false)
	self:make_static_frame(p, true)
	self.gui.chat_input_text = loveframes.Create("textinput", p)
	local t = self.gui.chat_input_text
	t:SetSize(390, 20)
	t:SetPos(5,5)
	t:SetRetainSize(false)
	t.OnEnter = function(object, text)				
		if text ~= "" then
			object:SetFocus(false)
			object:Clear()		
			local cmd = love.thread.getChannel("client_command")
			cmd:push("say")
			cmd:push(text)
		else
			object:SetFocus(false)
		end
	end
end

function guest:add_to_chat(s)
	local text = loveframes.Create("text")
	text:SetText(s)
	self.gui.chat_list:AddItem(text)
end

function guest:gui_list_stats(list)
	self.gui.stats_gui = {}
	for k,v in ipairs(self.stats) do
		self.gui.stats_gui[k] = loveframes.Create("text", list)
		self.gui.stats_gui[k]:SetText(k .. ": " .. v)
		self.gui.stats_gui[k]:SetShadowColor(200,200,200,255)
		self.gui.stats_gui[k]:SetState("game")
		list:AddItem(self.gui.char_gui[k])
	end
end

function guest:gui_set_stat(stat, value)
	print("setting stat ", stat)
	print("new value ", value)
	if not self.gui.stats_gui then self.gui.stats_gui = {} end
	self.gui.stats_gui[stat] = loveframes.Create("text", self.gui.char_info_panel)
	self.gui.stats_gui[stat]:SetText(stat .. ": " .. value)
	self.gui.stats_gui[stat]:SetShadowColor(200,200,200,255)
	self.gui.stats_gui[stat]:SetState('game')
	self.gui.char_info_panel:AddItem(self.gui.stats_gui[stat])
end

function guest:update_stat(stat, newValue)
	print("attempting to update stat " .. stat .. " to " .. newValue)
	if stat == "character_points" then
		self.character_points = newValue		
		if self.gui.character_points then
			self.gui.character_points:SetText(newValue)
		end
	elseif stat == "character_points_max" then
		self.character_points_max = newValue
	elseif stat == "training_points" then
		self.training_points = newValue
		if self.gui.training_points then
			self.gui.training_points:SetText(newValue)
		end
	elseif stat == "training_points_max" then
		self.training_points_max = newValue
	elseif stat == "name" then
		self.name = newValue
		self:gui_set_stat("name", newValue)
	elseif stat == "gender" then
		self.gender = newValue
		self:gui_set_stat("gender", newValue)
	else
		if not self.stats[stat] then 
			self.stats[stat] = {} 
		end
		if self.stats[stat] and newValue then
			self.stats[stat] = newValue
			if not self.stats_gui or not self.stats_gui[stat] then
				self:gui_set_stat(stat, newValue)
			else
				self.stats_gui[stat]:SetText(stat .. ": " .. newValue)
			end
		end
	end
end

function guest:setX(x)
	self.x = x
end

function guest:setY(y)
	self.y = y
end


function guest:exitedState()
	print("client exited guest state")
end